/**
 * Game 游戏类
 */
import Map from './Map.js';
import Food from './Food.js';
import Snake from './Snake.js';
import Event from './Event.js';

class Game extends Event{
    constructor(el, rect, toControl = null, toGrade = null) {
        super();
        this.map = new Map(el, rect);
        this.food = new Food(this.map.rows, this.map.cells);
        this.snake = new Snake(this.map);
        this.map.setData(this.snake.data);
        this.createFood();
        this.render();
        this.timer = 0;   // 定时器
        this.interval = 200;    // 定时器执行时间
        this.grade = 0;     // 得分
        this.toControl = toControl;
        this.keyDown = this.keyDown.bind(this);
        this.toGrade = toGrade;
    }
    // 开始游戏
    start() {
        this.move();
        this.control();
    }
    // 暂停游戏
    stop() {
        clearInterval(this.timer);
    }
    // 判断游戏是否结束
    isOver() {
        // 判断蛇头出了地图
        if (this.snake.data[0].x < 0 || this.snake.data[0].x >= this.map.cells || this.snake.data[0].y < 0 || this.snake.data[0].y >= this.map.rows) {
            return true;
        }

        // 判断蛇撞到了自己
        for (let i = 1; i < this.snake.data.length; i++) {
            if (this.snake.data[0].x === this.snake.data[i].x && this.snake.data[0].y === this.snake.data[i].y) {
                return true;
            }
        }
        return false;
    }
    // 向地图渲染数据
    render() {
        this.map.clearData();
        this.map.setData(this.snake.data);
        this.map.setData(this.food.data);
        this.map.render();
    }
    createFood() {
        this.food.create();
        if (this.map.include(this.food.data)) {
            this.createFood();
        }
    }
    // 判断是否迟到食物
    isEatFood() {
        return (this.snake.data[0].x === this.food.data.x && this.snake.data[0].y === this.food.data.y);
    }

    /**
     * overState  0: 中间停止，挂了   1：胜利了，游戏结束
     */
    // 结束游戏
    over(overState = 1) {
        this.toOver && this.toOver(overState);
        this.stop();
    }
    // 控制移动
    move() {
        this.stop();
        this.timer = setInterval(() => {
            this.map.clearData();
            this.snake.move();

            // 判断是否吃到食物
            if (this.isEatFood()) {
                this.snake.eatFood();
                this.food.create();
                this.grade++;
                this.changeGrade(this.grade);
                // 加快速度
                this.interval *= .9;
                this.stop();
                this.start();
                if (this.grade >= 20) {
                    this.over(1);
                }
            }

            if (this.isOver()) {
                this.over(0);
                return;
            }

            this.map.setData(this.food.data);
            this.map.setData(this.snake.data);
            this.map.render();
        }, this.interval);
    }

    keyDown(e) {
        const { keyCode } = e;
        let isDir;
        switch (keyCode) {
            case 37:
                isDir = this.snake.changeDirection('left');
                break;
            case 39:
                isDir = this.snake.changeDirection('right');
                break;
            case 38:
                isDir = this.snake.changeDirection('top');
                break;
            case 40:
                isDir = this.snake.changeDirection('bottom');
                break;
            default:
                break;
        }
        // console.log(isDir);
    }
    // 控制器
    control() {
        if (this.toControl) {
            this.toControl();
            return;
        }
        window.addEventListener("keydown",this.keyDown);
    }
    addControl(fn) {
        fn.call(this);
        window.removeEventListener("keydown", this.keyDown);
    }
    changeGrade(grade) {
        this.toGrade && this.toGrade(grade);
        this.dispatch('changeGrade', grade);
    }
}

export default Game;